#/
# @license Apache-2.0
#
# Copyright (c) 2017 The Stdlib Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#/

# VARIABLES #

# Define test runner to use when running JavaScript tests across multiple Node.js versions:
JAVASCRIPT_TEST_NODE_VERSIONS ?= $(TOOLS_DIR)/tests/scripts/test_node_versions

# Define the command-line options to be used when invoking the versions runner:
JAVASCRIPT_TEST_NODE_VERSIONS_FLAGS ?= \
	--versions $(NODE_VERSIONS)


# DEPENDENCIES #

ifeq ($(JAVASCRIPT_TEST_RUNNER), tape)
	include $(TOOLS_MAKE_LIB_DIR)/test/tape.mk
endif


# RULES #

#/
# Runs JavaScript unit tests.
#
# ## Notes
#
# -   Raw TAP output is piped to a TAP reporter.
# -   This command is useful when wanting to glob for JavaScript test files (e.g., run all JavaScript tests for a particular package).
#
#
# @param {string} [TESTS_FILTER] - file path pattern (e.g., `.*/blas/base/dasum/.*`)
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript
#
# @example
# make test-javascript TESTS_FILTER=".*/blas/base/dasum/.*"
#/
test-javascript: test-javascript-local

.PHONY: test-javascript

#/
# Runs a specified list of files containing JavaScript unit tests.
#
# ## Notes
#
# -   Raw TAP output is piped to a TAP reporter.
# -   This rule is useful when wanting to run a list of test files generated by some other command (e.g., a list of changed test files obtained via `git diff`).
#
#
# @param {string} FILES - list of test file paths
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-files FILES='/foo/test.js /bar/test.js'
#/
test-javascript-files: test-javascript-files-local

.PHONY: test-javascript-files

#/
# Runs JavaScript unit tests in the local environment.
#
# ## Notes
#
# -   In this context, "local" refers to the local development environment, as opposed to running in a headless browser or on CI.
#
#
# @param {string} [TESTS_FILTER] - file path pattern (e.g., `.*/blas/base/dasum/.*`)
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-local
#
# @example
# make test-javascript-local TESTS_FILTER=".*/blas/base/dasum/.*"
#/
test-javascript-local: $(NODE_MODULES)
ifeq ($(FAIL_FAST), true)
	$(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_REPORTER) || exit 1; \
	done
else
	$(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_REPORTER) || echo 'Tests failed.'; \
	done
endif

.PHONY: test-javascript-local

#/
# Runs, in the local environment, a specified list of files containing JavaScript unit tests.
#
# ## Notes
#
# -   In this context, "local" refers to the local development environment, as opposed to running in a headless browser or on CI.
# -   This rule is useful when wanting to run a list of JavaScript test files generated by some other command (e.g., a list of changed JavaScript test files obtained via `git diff`).
#
#
# @param {string} FILES - list of JavaScript test file paths
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-files-local FILES='/foo/test.js /bar/test.js'
#/
test-javascript-files-local: $(NODE_MODULES)
ifeq ($(FAIL_FAST), true)
	$(QUIET) for test in $(FILES); do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_REPORTER) || exit 1; \
	done
else
	$(QUIET) for test in $(FILES); do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_REPORTER) || echo 'Tests failed.'; \
	done
endif

.PHONY: test-javascript-files-local

#/
# Runs JavaScript unit tests and summarizes aggregated TAP output.
#
# ## Notes
#
# -   This command is useful when wanting to glob for JavaScript test files (e.g., run all JavaScript tests for a particular package).
#
#
# @param {string} [TESTS_FILTER] - file path pattern (e.g., `.*/blas/base/dasum/.*`)
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-summary
#
# @example
# make test-javascript-summary TESTS_FILTER=".*/blas/base/dasum/.*"
#/
test-javascript-summary: $(NODE_MODULES)
ifeq ($(FAIL_FAST), true)
	$(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_SUMMARY) || exit 1; \
	done
else
	$(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_SUMMARY) || echo 'Tests failed.'; \
	done
endif

.PHONY: test-javascript-summary

#/
# Runs a specified list of files containing JavaScript unit tests and summarizes aggregated TAP output.
#
# ## Notes
#
# -   This rule is useful when wanting to run a list of JavaScript test files generated by some other command (e.g., a list of changed JavaScript test files obtained via `git diff`).
#
#
# @param {string} FILES - list of JavaScript test file paths
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-files-summary FILES='/foo/test.js /bar/test.js'
#/
test-javascript-files-summary: $(NODE_MODULES)
ifeq ($(FAIL_FAST), true)
	$(QUIET) for test in $(FILES); do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_SUMMARY) || exit 1; \
	done
else
	$(QUIET) for test in $(FILES); do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_SUMMARY) || echo 'Tests failed.'; \
	done
endif

.PHONY: test-javascript-files-summary

#/
# Runs JavaScript unit tests and minimizes aggregated TAP output.
#
# ## Notes
#
# -   This command is useful when wanting to glob for JavaScript test files (e.g., run all JavaScript tests for a particular package).
#
#
# @param {string} [TESTS_FILTER] - file path pattern (e.g., `.*/blas/base/dasum/.*`)
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-min
#
# @example
# make test-javascript-min TESTS_FILTER=".*/blas/base/dasum/.*"
#/
test-javascript-min: $(NODE_MODULES)
ifeq ($(FAIL_FAST), true)
	$(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_MIN) || exit 1; \
	done
else
	$(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_MIN) || echo 'Tests failed.'; \
	done
endif

.PHONY: test-javascript-min

#/
# Runs a specified list of files containing JavaScript unit tests and minimizes aggregated TAP output.
#
# ## Notes
#
# -   This rule is useful when wanting to run a list of JavaScript test files generated by some other command (e.g., a list of changed JavaScript test files obtained via `git diff`).
#
#
# @param {string} FILES - list of JavaScript test file paths
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-files-min FILES='/foo/test.js /bar/test.js'
#/
test-javascript-files-min: $(NODE_MODULES)
ifeq ($(FAIL_FAST), true)
	$(QUIET) for test in $(FILES); do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_MIN) || exit 1; \
	done
else
	$(QUIET) for test in $(FILES); do \
		echo ''; \
		echo "Running test: $$test"; \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_MIN) || echo 'Tests failed.'; \
	done
endif

.PHONY: test-javascript-files-min

#/
# Runs JavaScript unit tests and generates raw TAP output.
#
# ## Notes
#
# -   This command is useful when wanting to glob for JavaScript test files (e.g., run all JavaScript tests for a particular package).
#
#
# @param {string} [TESTS_FILTER] - file path pattern (e.g., `.*/blas/base/dasum/.*`)
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-tap
#
# @example
# make test-javascript-tap TESTS_FILTER=".*/blas/base/dasum/.*"
#/
test-javascript-tap: $(NODE_MODULES)
ifeq ($(FAIL_FAST), true)
	$(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test || exit 1; \
	done
else
	$(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test || echo 'Tests failed.'; \
	done
endif

.PHONY: test-javascript-tap

#/
# Runs a specified list of files containing JavaScript unit tests and generates raw TAP output.
#
# ## Notes
#
# -   This rule is useful when wanting to run a list of JavaScript test files generated by some other command (e.g., a list of changed JavaScript test files obtained via `git diff`).
#
#
# @param {string} FILES - list of JavaScript test file paths
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-files-tap FILES='/foo/test.js /bar/test.js'
#/
test-javascript-files-tap: $(NODE_MODULES)
ifeq ($(FAIL_FAST), true)
	$(QUIET) for test in $(FILES); do \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test || exit 1; \
	done
else
	$(QUIET) for test in $(FILES); do \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test || echo 'Tests failed.'; \
	done
endif

.PHONY: test-javascript-files-tap

#/
# Runs JavaScript unit tests and converts TAP output to xUnit XML.
#
# ## Notes
#
# -   This command is useful when wanting to glob for JavaScript test files (e.g., run all JavaScript tests for a particular package).
#
#
# @param {string} [TESTS_FILTER] - file path pattern (e.g., `.*/blas/base/dasum/.*`)
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-xunit
#
# @example
# make test-javascript-xunit TESTS_FILTER=".*/blas/base/dasum/.*"
#/
test-javascript-xunit: $(NODE_MODULES)
ifeq ($(FAIL_FAST), true)
	$(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_XUNIT) || exit 1; \
	done
else
	$(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_XUNIT) || echo 'Tests failed.'; \
	done
endif

.PHONY: test-javascript-xunit

#/
# Runs a specified list of files containing JavaScript unit tests and converts TAP output to xUnit XML.
#
# ## Notes
#
# -   This rule is useful when wanting to run a list of JavaScript test files generated by some other command (e.g., a list of changed JavaScript test files obtained via `git diff`).
#
#
# @param {string} FILES - list of JavaScript test file paths
# @param {string} [JAVASCRIPT_TEST_RUNNER] - JavaScript test runner
# @param {*} [FAST_FAIL] - flag indicating whether to stop running tests upon encountering a test failure
#
# @example
# make test-javascript-files-xunit FILES='/foo/test.js /bar/test.js'
#/
test-javascript-files-xunit: $(NODE_MODULES)
ifeq ($(FAIL_FAST), true)
	$(QUIET) for test in $(FILES); do \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_XUNIT) || exit 1; \
	done
else
	$(QUIET) for test in $(FILES); do \
		NODE_ENV="$(NODE_ENV_TEST)" \
		NODE_PATH="$(NODE_PATH_TEST)" \
		$(NODE) $(NODE_FLAGS_TEST) $(JAVASCRIPT_TEST) \
			$(JAVASCRIPT_TEST_FLAGS) \
			$$test \
		| $(TAP_XUNIT) || echo 'Tests failed.'; \
	done
endif

.PHONY: test-javascript-files-xunit

#/
# Runs JavaScript unit tests against specific Node.js versions.
#
# TODO: pipe a list of files to the script, thus avoiding argument list too long errors.
# TODO: create a separate recipe for providing an explicit file list using `$FILES`. Once done, update `tools-test` recipes.
#
# @example
# make test-node-versions
#/
test-node-versions: $(NODE_MODULES)
	$(QUIET) $(MAKE_EXECUTABLE) $(JAVASCRIPT_TEST_NODE_VERSIONS)
	$(QUIET) $(JAVASCRIPT_TEST_NODE_VERSIONS) $(JAVASCRIPT_TEST_NODE_VERSIONS_FLAGS) $(TESTS)

.PHONY: test-node-versions
